package link.jfire.socket.socketclient.listen;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import link.jfire.socket.socketserver.exception.TimeoutException;

public class ReadResult implements Future<Object>
{
    private final Lock         lock;
    private final Condition    finishRead;
    private volatile boolean   finishStatus = false;
    private volatile Throwable readException;
    private volatile Object    result;
    private final long         readTiemout;
    
    public ReadResult(Lock lock, Condition finishRead, ClientChannelInfo clientChannelInfo)
    {
        this.lock = lock;
        this.finishRead = finishRead;
        readTiemout = clientChannelInfo.getReadTimeout();
    }
    
    @Override
    public boolean cancel(boolean mayInterruptIfRunning)
    {
        throw new RuntimeException("数据已经发送，操作无法撤销，必须等待数据读取完毕。否则造成通道内的数据状态异常");
    }
    
    @Override
    public boolean isCancelled()
    {
        throw new RuntimeException("数据已经发送，操作无法撤销，必须等待数据读取完毕。否则造成通道内的数据状态异常");
    }
    
    @Override
    public boolean isDone()
    {
        return finishStatus;
    }
    
    @Override
    public Object get() throws InterruptedException, ExecutionException
    {
        lock.lock();
        try
        {
            while (finishStatus == false)
            {
                if (finishRead.await(readTiemout, TimeUnit.MILLISECONDS))
                {
                    
                }
                else
                {
                    throw new ExecutionException(new TimeoutException(readTiemout));
                }
                
            }
            if (readException != null)
            {
                throw new ExecutionException(readException);
            }
            return result;
        }
        catch (Exception e)
        {
            throw new ExecutionException(e);
        }
        finally
        {
            lock.unlock();
        }
        
    }
    
    @Override
    public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException
    {
        lock.lock();
        try
        {
            while (finishStatus == false)
            {
                if (finishRead.await(timeout, unit))
                {
                    
                }
                else
                {
                    throw new ExecutionException(new TimeoutException(timeout));
                }
            }
            if (readException != null)
            {
                throw new ExecutionException(readException);
            }
            return result;
        }
        finally
        {
            lock.unlock();
        }
    }
    
    public void setFinishStatus(boolean finishStatus)
    {
        this.finishStatus = finishStatus;
    }
    
    public void setReadException(Throwable readException)
    {
        this.readException = readException;
    }
    
    public void setResult(Object result)
    {
        this.result = result;
    }
    
}
